package com.lixin.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lixin.mapper.UserMapper;
import com.lixin.pojo.User;
import com.lixin.pojo.dto.UserLoginDto;
import com.lixin.pojo.dto.UserModifyDto;
import com.lixin.pojo.dto.UserRegisterDto;
import com.lixin.pojo.mapper.UserModifyDtoMapper;
import com.lixin.pojo.mapper.UserRegisterDtoMapper;
import com.lixin.service.UserService;
import com.lixin.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 * @description 针对表【shop_user】的数据库操作Service实现
 * @createDate 2023-11-24 13:42:28
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRegisterDtoMapper userRegisterDtoMapper;
    @Autowired
    private UserModifyDtoMapper userModifyDtoMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;


    @Override
    public Result findWithPage(String currentPage, String pageSize) {
        if (!ValidatorUtil.isNumber(currentPage) || !ValidatorUtil.isNumber(pageSize)) {
            return Result.build(ResultCode.PARAM_ERROR);
        }
        IPage<User> page = new Page<>(Long.parseLong(currentPage), Long.parseLong(pageSize));
        userMapper.selectPage(page, null);
        return Result.success(Pagination.build(page));
    }

    @Override
    public Result register(UserRegisterDto userRegisterDto) {
        if (!ValidatorUtil.lengthLimit(1, 8, userRegisterDto.getUserNickname()) ||
            !ValidatorUtil.lengthLimit(6, 16, userRegisterDto.getUserAccount()) ||
            !ValidatorUtil.lengthLimit(6, 16, userRegisterDto.getUserPassword()) ||
            !userRegisterDto.getUserPassword().equals(userRegisterDto.getConfirmUserPassword())) {
            return Result.build(ResultCode.PARAM_ERROR);
        }

        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getUserAccount, userRegisterDto.getUserAccount());
        User user = userMapper.selectOne(userQueryWrapper);
        if (user != null && user.getUserId() > 0) {
            return Result.build(ResultCode.USER_ACCOUNT_USED);
        }

        User insertUser = userRegisterDtoMapper.userRegisterDtoToUser(userRegisterDto);
        insertUser.setUserPassword(DigestUtil.md5Hex(insertUser.getUserPassword()));
        int rows = userMapper.insert(insertUser);
        if (rows <= 0) {
            return Result.build(ResultCode.USER_REGISTER_ERROR);
        }
        return Result.build(ResultCode.USER_REGISTER_SUCCESS);
    }

    @Override
    public Result checkAccount(String account) {
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getUserAccount, account);
        User user = userMapper.selectOne(userQueryWrapper);
        if (user != null && user.getUserId() > 0) {
            return Result.build(ResultCode.USER_ACCOUNT_USED);
        }
        return Result.build(ResultCode.USER_ACCOUNT_CAN_USE);
    }

    @Override
    public Result del(String id) {
        if (!ValidatorUtil.isNumber(id)) {
            return Result.build(ResultCode.PARAM_ERROR);
        }
        int rows = userMapper.deleteById(id);
        if (rows <= 0) {
            return Result.fail();
        }
        return Result.success();
    }

    @Override
    public Result login(UserLoginDto userLoginDto) {
        System.out.println("service:" + userLoginDto);
        if (!ValidatorUtil.lengthLimit(6, 16, userLoginDto.getUserAccount()) ||
            !ValidatorUtil.lengthLimit(6, 16, userLoginDto.getUserPassword())) {
            return Result.build(ResultCode.PARAM_ERROR);
        }

        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getUserAccount, userLoginDto.getUserAccount());
        User user = userMapper.selectOne(userQueryWrapper);
        if (user == null) {
            return Result.build(ResultCode.USER_ACCOUNT_NOT_EXISTED);
        }
        if (!user.getUserPassword().equals(DigestUtil.md5Hex(userLoginDto.getUserPassword()))) {
            return Result.build(ResultCode.USER_PASSWORD_ERROR);
        }

        HashMap<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getUserId());
        String token = JwtUtil.generateToken(claims);
        if (!ValidatorUtil.notBlank(token)) {
            return Result.build(ResultCode.TOKEN_GEN_ERROR);
        }
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        operations.set(token, token, TimeEnum.REDIS_TOKEN_EXPIRE_TIME.getTime(), TimeUnit.DAYS);

        return Result.build(ResultCode.USER_LOGIN_SUCCESS, token);
    }

    @Override
    public Result detail() {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Long id = (Long)claims.get("userId");
        User user = userMapper.selectById(id);
        if (user == null) {
            return Result.fail();
        }
        return Result.success(user);
    }

    @Override
    public Result modify(UserModifyDto userModifyDto, String token) {
        if (userModifyDto.getUserNickname() != null && !ValidatorUtil.lengthLimit(1, 8, userModifyDto.getUserNickname())) {
            return Result.build(ResultCode.PARAM_ERROR);
        }
        if (userModifyDto.getUserAccount() != null && !ValidatorUtil.lengthLimit(6, 16, userModifyDto.getUserAccount())) {
            return Result.build(ResultCode.PARAM_ERROR);
        }
        if (userModifyDto.getUserPassword() != null && !ValidatorUtil.lengthLimit(6, 16, userModifyDto.getUserPassword())) {
            return Result.build(ResultCode.PARAM_ERROR);
        }

        Map<String, Object> claims = ThreadLocalUtil.get();
        Long id = (Long)claims.get("userId");
        Integer version = userMapper.selectById(id).getUserVersion();

        User user = userModifyDtoMapper.userModifyDtoToUser(userModifyDto);
        user.setUserId(id);
        user.setUserUpdated(LocalDateTime.now());
        user.setUserVersion(version);
        if (user.getUserPassword() != null) {
            user.setUserPassword(DigestUtil.md5Hex(user.getUserPassword()));
        }
        int rows = userMapper.updateById(user);
        if (rows <= 0) {
            return Result.fail();
        }
        if (user.getUserPassword() != null) {
            redisTemplate.delete(token);
        }

        return Result.success();
    }
}




